package com.ww.microrpc.loadbalancer;

import com.netflix.client.ClientException;
import com.netflix.client.IClientConfigAware;
import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.LoadBalancerContext;
import com.ww.microrpc.netty.RequestHolder;
import com.ww.microrpc.netty.protocol.ResponseMessage;

/**
 * @author iiwan
 */
public abstract class AbstractLoadBalancerAwareClient extends LoadBalancerContext implements IClientConfigAware {
    public abstract ResponseMessage executeFuture(RequestHolder request);

    public AbstractLoadBalancerAwareClient(ILoadBalancer lb) {
        super(lb);
    }

    /**
     * Delegate to {@link #initWithNiwsConfig(IClientConfig)}
     * @param clientConfig
     */
    public AbstractLoadBalancerAwareClient(ILoadBalancer lb, IClientConfig clientConfig) {
        super(lb, clientConfig);
    }

    /**
     * Determine if operation can be retried if an exception is thrown. For example, connect
     * timeout related exceptions
     * are typically retriable.
     *
     */
    public boolean isRetriableException(Throwable e) {
        if (getRetryHandler() != null) {
            return getRetryHandler().isRetriableException(e, true);
        }
        return false;
    }

    public ResponseMessage executeWithLoadBalancer(RequestHolder request) throws ClientException {
        return executeWithLoadBalancer(request, null);
    }

    /**
     * This method should be used when the caller wants to dispatch the request to a server chosen by
     * the load balancer, instead of specifying the server in the request's URI.
     * It calculates the final URI by calling {@link #reconstructURIWithServer(com.netflix.loadbalancer.Server, java.net.URI)}
     * and then calls
     *
     * @param request request to be dispatched to a server chosen by the load balancer. The URI can be a partial
     * URI which does not contain the host name or the protocol.
     */
    public ResponseMessage executeWithLoadBalancer(final RequestHolder request, final IClientConfig requestConfig) throws ClientException {
        try {
            // 负载均衡执行请求
            return null;
        } catch (Exception e) {
            Throwable t = e.getCause();
            if (t instanceof ClientException) {
                throw (ClientException) t;
            } else {
                throw new ClientException(e);
            }
        }

    }

    public abstract RequestSpecificRetryHandler getRequestSpecificRetryHandler(RequestHolder request, IClientConfig requestConfig);



    @Deprecated
    public boolean isRetriable(RequestHolder request) {
        if (request.isRetriable()) {
            return true;
        }

        return false;
    }
}
